﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Text;

namespace APC
{
    class InputValidator
    {

        #region Enum

        public enum InputValidationType { TypeText, TypeNumeric }

        private enum ValidationTextType
        {
            NumericBelow = 1,
            NumericAbove = 2,
            NumericHeigh = 3, //Alert user that value is heigh, but user cann proceed...
            NumericDecimalNotAllowed = 4,
            NumericTextNotAllowed = 5,
            TextLengthBelow = 6,
            TextLengthAbove = 7
        }


        #endregion

        #region Declarations

        decimal InputValueNumeric = 0;
        ValidationTextType valText;
        // 8 = back space, 37 = left arrow, 39 = right arrow, 46 = Delete
        int[] AllowedKeyValues = { 8, 37, 39, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105 };

        #endregion

        #region Properties

        /// <summary>
        /// User input from textbox to be validated
        /// </summary>
        public string InputValue
        {
            set 
            { 
                _InputValue = value;
               
                //Reset values every time a validaton is made
                _MinLength = 0;
                _MaxLength = 0;
                _MinValue = 0;
                _MaxValue = 0;
                _LargeNumberAlert = 0;
                _ValidButHeigh = false;
                _Valid = true;
                _DecimalAllowed = false;
                _ValidOnlyOnce = true; //Set flag to avoid multiple evaluations
            }
        }
        private string _InputValue = "";

        /// <summary>
        /// Sends the translated text "Order Quantum" or "Order Number" into Validation Message
        /// </summary>
        public string InputboxFrindlyName
        {
            set { _InputboxFrindlyName = value; }
        }
        private string _InputboxFrindlyName = "";

        /// <summary>
        /// TypeText or TypeNumeric
        /// </summary>
        public InputValidationType eInputValidationType
        {
            set { _InputValidationType = value; }
        }
        private InputValidationType _InputValidationType;

        /// <summary>
        /// For text a minimum length can be set
        /// </summary>
        public int MinLength
        {
            set { _MinLength = value; }
        }
        private int _MinLength = 0;

        /// <summary>
        /// For text a maximum length can be set
        /// </summary>
        public int MaxLength
        {
            set { _MaxLength = value; }
        }
        private int _MaxLength = 0;

        /// <summary>
        /// For numeric a minimum value can be set
        /// </summary>
        public decimal MinValue
        {
            set { _MinValue = value; }
        }
        private decimal _MinValue = 0;

        /// <summary>
        /// For numeric a maximum value can be set
        /// </summary>
        public decimal MaxValue
        {
            set { _MaxValue = value; }
        }
        private decimal _MaxValue = 0;

        /// <summary>
        /// Return a message string if validation fails
        /// </summary>
        public string ValidationMessage
        {
            get { return _ValidationMessage; }
        }
        private string _ValidationMessage = "";

        /// <summary>
        /// For numeric inputbox an alert can be rasied if user sets numeric value above LargeNumberAlert
        /// </summary>
        public int LargeNumberAlert
        {
            set { _LargeNumberAlert = value; }
        }
        private int _LargeNumberAlert = 0;

        /// <summary>
        /// Returns true if a friendly message will be returned to user on heigh value input
        /// </summary>
        public bool ValidButHeigh
        {
            set { _ValidButHeigh = value; }
            get { return _ValidButHeigh; }
        }
        private bool _ValidButHeigh = false;

        /// <summary>
        /// Flag for only evaluation 1 time per change
        /// </summary>
        public bool ValidOnlyOnce
        {
            set { _ValidOnlyOnce = value; }
            get { return _ValidOnlyOnce; }
        }
        private bool _ValidOnlyOnce = false;
        
        /// <summary>
        /// Returns false if userinput is invalid
        /// </summary>
        public bool Valid
        {
            set { _Valid = value; }
            get { return _Valid; }
        }
        private bool _Valid = true;

        /// <summary>
        /// If DecimalAllowed = false, user will be warned that only whole numbers ar allowed
        /// </summary>
        public bool DecimalAllowed
        {
            set { _DecimalAllowed = value; }
            get { return _DecimalAllowed; }
        }
        private bool _DecimalAllowed = true;


        /// <summary>
        /// Set icon for MessageBox
        /// </summary>
        public System.Windows.Forms.MessageBoxIcon MessageBoxIcon
        {
            set { _MessageBoxIcon = value; }
            get { return _MessageBoxIcon; }
        }
        private System.Windows.Forms.MessageBoxIcon _MessageBoxIcon;

        #endregion

        #region Methods

        public bool Validate()
        {
            _Valid = true;

            switch (_InputValidationType)
            {
                case InputValidationType.TypeNumeric:
                    //Try cast value as numeric and evaluate

                    if (IsNumber(_InputValue))
                    {
                        Decimal IntValue = Convert.ToDecimal(_InputValue);

                        if (!_DecimalAllowed)
                        {
                            bool odd = (IntValue % 1 != 0);

                            if (odd) 
                            { 
                                _Valid = false;
                                valText = ValidationTextType.NumericDecimalNotAllowed;
                            }
                        }


                        if (IntValue < _MinValue)
                        { 
                            _Valid = false;
                            valText = ValidationTextType.NumericBelow;
                        }
                        if (_MaxValue > 0)
                        {
                            if (IntValue > _MaxValue) 
                            { 
                                _Valid = false; 
                                 valText = ValidationTextType.NumericAbove;
                            }
                        }
                        if (_Valid)
                        {
                            if (_LargeNumberAlert > 0 && InputValueNumeric > _LargeNumberAlert) //Raises a friendly message saying that the entered value is heigh
                            {
                                _Valid = false;
                                _ValidButHeigh = true;
                                 valText = ValidationTextType.NumericHeigh;
                            }
                        }

                    }
                    else
                    {   
                        _Valid = false;
                        valText = ValidationTextType.NumericTextNotAllowed;
                    }
                    break;

                case InputValidationType.TypeText:

                    if (_InputValue.Length < _MinLength) 
                    { 
                        _Valid = false; 
                         valText = ValidationTextType.TextLengthBelow;
                    }
                    if (_MaxLength > 0)
                    {
                        if (_InputValue.Length > _MaxLength) 
                        { 
                            _Valid = false; 
                             valText = ValidationTextType.TextLengthAbove;
                        }
                    }
                    break;
            }
 
            if (!_Valid)
            {
                WriteValidationMessage();
            }

            //Finally return the result of validation
            return _Valid;
        }

        /// <summary>
        /// On each keypress evaluate if numeric or BACK
        /// </summary>
        /// <param name="KeyValue"></param>
        /// <returns></returns>
        public bool ValidateNumeric(int KeyValue)
        {
           return !AllowedKeyValues.Contains(KeyValue);
        }

        private void WriteValidationMessage()
        {

            String msg = "";
            _MessageBoxIcon = System.Windows.Forms.MessageBoxIcon.Exclamation;

            switch (_InputValidationType)
            {
                case InputValidationType.TypeNumeric:

                    switch (valText)
                    {
                        case ValidationTextType.NumericBelow:
                            msg = String.Format(_InputboxFrindlyName + ":{0}{0}Must be heigher than {1}!", Environment.NewLine, _MinValue);
                            break;

                        case ValidationTextType.NumericAbove:
                            msg = String.Format(_InputboxFrindlyName + ":{0}{0}Must be less than {1}!", Environment.NewLine, _MaxValue);
                            break;

                        case ValidationTextType.NumericDecimalNotAllowed:
                            msg = String.Format(_InputboxFrindlyName + ":{0}{0}Must not contain decimal!", Environment.NewLine);
                            break;

                        case ValidationTextType.NumericHeigh:
                            msg = String.Format(_InputboxFrindlyName + ":{0}{0}Value is relatively heigh!", Environment.NewLine);
                            _MessageBoxIcon = System.Windows.Forms.MessageBoxIcon.Question;
                            _ValidButHeigh = true;
                            break;

                        case ValidationTextType.NumericTextNotAllowed:
                            msg = String.Format(_InputboxFrindlyName + ":{0}{0}Only numbers are allowed!", Environment.NewLine);
                            _MessageBoxIcon = System.Windows.Forms.MessageBoxIcon.Exclamation;
                            break;
                    }  
                    break;

                case InputValidationType.TypeText:

                    switch (valText)
                    {
                        case ValidationTextType.TextLengthAbove:
                            _MessageBoxIcon = System.Windows.Forms.MessageBoxIcon.Exclamation;
                            msg = String.Format(_InputboxFrindlyName + ":{0}{0}Text is to long!", Environment.NewLine);
                            break;

                        case ValidationTextType.TextLengthBelow:
                            _MessageBoxIcon = System.Windows.Forms.MessageBoxIcon.Exclamation;
                            msg = String.Format(_InputboxFrindlyName + ":{0}{0}Text is to short!", Environment.NewLine);
                            break;

                    }
                    break;

            }

           _ValidationMessage = msg;
        }

        /// <summary>
        /// Validation method for testing numeric value
        /// </summary>
        /// <returns></returns>
        private bool IsNumber(string InputValue)
        {
            bool res = false;
            try
            {
                if (!string.IsNullOrEmpty(InputValue) && ((InputValue.Length != 1) || (InputValue != "-")))
                {
                    Decimal d = decimal.Parse(InputValue, CultureInfo.CurrentCulture);
                    InputValueNumeric = d;
                    res = true;
                }
            }
            catch
            {
                res = false;
            }
            return res;
        }

        #endregion


    }
}
